using CfgTable;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;

namespace IQIGame.Onigao.GamePlay
{
    public class UIN_PetBaseInfo : UIBaseNode
    {
        #region Template Generate,don't modify
        protected class UIB_UIN_PetBaseInfo
        {
            #region ObjectBinding Generate
            public UnityEngine.GameObject skillCell { protected set; get; }
            public IQIGame.Onigao.Framework.ExText skillDes { protected set; get; }
            public IQIGame.Onigao.Framework.ExText useCD { protected set; get; }
            public IQIGame.Onigao.Framework.ExText defaultCD { protected set; get; }
            public UnityEngine.GameObject petInitAttr { protected set; get; }
            public UnityEngine.GameObject slotCell { protected set; get; }
            public IQIGame.Onigao.Framework.ExButton name { protected set; get; }
            public IQIGame.Onigao.Framework.ExText textName { protected set; get; }
            public IQIGame.Onigao.Framework.ExText textLvMax { protected set; get; }
            public IQIGame.Onigao.Framework.ExText textLv { protected set; get; }
            public IQIGame.Onigao.Framework.ExProgressBar expBar { protected set; get; }
            public IQIGame.Onigao.Framework.ExButton btnLockState { protected set; get; }
            public IQIGame.Onigao.Framework.ExText textType { protected set; get; }
            public UnityEngine.GameObject costMoney { protected set; get; }
            public IQIGame.Onigao.Framework.ExButton btnUpdate { protected set; get; }
            public IQIGame.Onigao.Framework.ExButton btnFreedom { protected set; get; }
            public UnityEngine.GameObject pabilityGroup { protected set; get; }
            public virtual void InitBinding(ObjectBinding __binding)
            {
                __binding.TryGetVariableValue<UnityEngine.GameObject>("skillCell", out var __tbv0);
                this.skillCell = __tbv0;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExText>("skillDes", out var __tbv1);
                this.skillDes = __tbv1;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExText>("useCD", out var __tbv2);
                this.useCD = __tbv2;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExText>("defaultCD", out var __tbv3);
                this.defaultCD = __tbv3;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("petInitAttr", out var __tbv4);
                this.petInitAttr = __tbv4;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("slotCell", out var __tbv5);
                this.slotCell = __tbv5;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExButton>("name", out var __tbv6);
                this.name = __tbv6;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExText>("textName", out var __tbv7);
                this.textName = __tbv7;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExText>("textLvMax", out var __tbv8);
                this.textLvMax = __tbv8;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExText>("textLv", out var __tbv9);
                this.textLv = __tbv9;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExProgressBar>("expBar", out var __tbv10);
                this.expBar = __tbv10;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExButton>("btnLockState", out var __tbv11);
                this.btnLockState = __tbv11;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExText>("textType", out var __tbv12);
                this.textType = __tbv12;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("costMoney", out var __tbv13);
                this.costMoney = __tbv13;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExButton>("btnUpdate", out var __tbv14);
                this.btnUpdate = __tbv14;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExButton>("btnFreedom", out var __tbv15);
                this.btnFreedom = __tbv15;
                __binding.TryGetVariableValue<UnityEngine.GameObject>("pabilityGroup", out var __tbv16);
                this.pabilityGroup = __tbv16;
            }
            #endregion ObjectBinding Generate 
        }
        #endregion Template Generate,don't modify

        #region fields
        private UIN_HeroSkillCell skill;
        private ListScrollAdapter<UIN_CommonTitleValue> baseAttrs;
        private ListScrollAdapter<UIN_PetSlotCell> slots;
        private ListScrollAdapter<UIN_PetPabilityGroup> pabilityGroups;
        private UIN_CostMoney costMoney = null;

        private Pet pet = null;
        private int slotCount = 0;

        #endregion fields

        #region properties

        protected UIB_UIN_PetBaseInfo ui { get; set; }
        protected UIMsgDispatcher uiMsgDispatcher => this._msgDispatcher as UIMsgDispatcher;

        #endregion properties

        protected override void BeforeInit()
        {
            ui = new UIB_UIN_PetBaseInfo();
            ui.InitBinding(this.csObjBind);
        }

        protected override void OnInit()
        {
            this.skill = this.InitChildNode<UIN_HeroSkillCell>(this.ui.skillCell);
            this.baseAttrs = this.InitListScroll<UIN_CommonTitleValue>(this.ui.petInitAttr, this.OnBaseAttrChanged);
            this.slots = this.InitListScroll<UIN_PetSlotCell>(this.ui.slotCell, this.OnSlotChanged);

            this.pabilityGroups = this.InitListScroll<UIN_PetPabilityGroup>(this.ui.pabilityGroup, this.OnPabilityGroupChanged);
            this.costMoney = this.InitChildNode<UIN_CostMoney>(this.ui.costMoney);
        }

        protected override void OnShow()
        {

        }

        protected override void OnHide()
        {
            this.ClearData();
        }

        /// <summary>
        /// 添加UGUI侦听
        /// </summary>
        protected override void AddUGUIListener()
        {
            this.ui.btnUpdate.onClick.AddListener(this.OnClickBtnUpdate);
            this.ui.btnFreedom.onClick.AddListener(this.OnClickBtnFreedom);
            this.ui.btnLockState.onClick.AddListener(this.OnClickBtnChangeLockState);
            this.ui.name.onClick.AddListener(this.OnClickChangeName);
        }

        /// <summary>
        /// 添加全局侦听（MsgDispatcher）
        /// </summary>
        protected override void AddMsgListeners()
        {
            this.uiMsgDispatcher.AddListener(MsgEventType.PetRenameSuccess, this.OnMsgPetRenameSuccess);
        }

        protected override void OnDispose()
        {
            this.ClearData();
        }

        #region methonds

        public void Show(Pet pet)
        {
            if (pet == null)
            {
                this.Hide();
                return;
            }
            this.SetData(pet);
            this.Show();
            this.ShowSkill();
            this.ShowBaseAttrs();
            this.ShowSlots();
            this.ShowPabilityGroups();
            this.ShowBaseInfo();
        }

        private void SetData(Pet pet)
        {
            this.pet = pet;
            var cfg = this.pet.cfgData;
            this.slotCount = cfg.RandomPabilitySlotUnlockLv.Count + cfg.ExtraSlotNum;
        }

        private void ClearData()
        {
            this.pet = null;
            this.slotCount = 0;
        }

        private void ShowSkill()
        {
            var skillData = this.pet.skillData;
            var cfgSkill = skillData.cfgData;
            this.skill.Show(skillData);
            this.skill.ShowName(cfgSkill.Name);

            this.ui.skillDes.text = skillData.cfgLv.EffectText;

            this.ui.defaultCD.text = APIUIPet.GetStrInitialCoolDown(cfgSkill.InitialCoolDown);
            this.ui.useCD.text = APIUIPet.GetStrCoolDown(cfgSkill.CoolDown);
        }

        private void ShowBaseAttrs()
        {
            var cfg = this.pet.cfgData;
            this.baseAttrs.RefillCells(cfg.AttType.Count);
        }

        private void OnBaseAttrChanged(UIN_CommonTitleValue item, int index)
        {
            var cfg = this.pet.cfgData;
            int cid = cfg.AttType[index];
            int val = cfg.AttValue[index];
            var cfgAttribute = TableCenter.attribute.Get(cid);
            string strVal = "+" + APIAttributeUIUtils.GetStrAttributeValue(cfgAttribute.ShowType, val);
            item.Show(strVal, cfgAttribute.Name);
        }

        private void ShowSlots()
        {
            int cnt = this.slotCount;
            this.slots.RefillCells(cnt);
        }

        private void OnSlotChanged(UIN_PetSlotCell item, int index)
        {
            var slotType = this.GetSlotType(index);
            item.Show(slotType, index, this.OnCallClickSlot);
        }

        private UIPetSlotType GetSlotType(int index)
        {
            int numCurr = index + 1;
            int useCount = this.pet.GetUsedSlotCount();
            if (useCount >= numCurr)
            {
                return UIPetSlotType.Used;
            }

            int itemUnlockCount = this.pet.unlockSlot;
            int lvUnlockCount = this.GetLvUnlockSlotCount();
            int unLockCount = itemUnlockCount + lvUnlockCount;
            if (unLockCount >= numCurr)
            {
                return UIPetSlotType.Unlock;
            }
            int lvCount = this.pet.cfgData.RandomPabilitySlotUnlockLv.Count;
            int numLv = numCurr - itemUnlockCount;
            if (lvCount >= numLv)
            {
                return UIPetSlotType.LockByLv;
            }
            return UIPetSlotType.LockByItem;
        }

        private int GetLvUnlockSlotCount()
        {
            int cnt = 0;
            foreach (var unlockLv in this.pet.cfgData.RandomPabilitySlotUnlockLv)
            {
                if (this.pet.level >= unlockLv)
                    cnt++;
            }
            return cnt;
        }

        private void OnCallClickSlot(UIPetSlotType slotType, int cellIndx)
        {
            switch (slotType)
            {
                case UIPetSlotType.LockByLv:
                    this.UnlockSlotNeedUpPetLv(cellIndx);
                    break;
                case UIPetSlotType.LockByItem:
                    this.UnlockSlotNeedCostItem();
                    break;
                default:
                    break;
            }
        }

        private void UnlockSlotNeedUpPetLv(int cellIndex)
        {
            int itemUnlockCount = this.pet.unlockSlot;
            int lvUnlockCount = this.GetLvUnlockSlotCount();
            int numCurr = (cellIndex + 1);
            int numLock = numCurr - itemUnlockCount - lvUnlockCount;

            var slotUnlockLvList = this.pet.cfgData.RandomPabilitySlotUnlockLv;
            int indexSlotUnlockLv = numLock + lvUnlockCount - 1;
            int slotUnlockLv = slotUnlockLvList[indexSlotUnlockLv];
            NoticeModule.ShowNoticeNoCall(APIUIPet.NoticeCid_SlotUnlockLv, slotUnlockLv.ToString());
        }

        private void UnlockSlotNeedCostItem()
        {
            var slotCostCidNum = TableCenter.global.PetUnlockAttributeSlotCost;
            int itemCid = slotCostCidNum[0];
            int itemCost = slotCostCidNum[1];
            int itemHave = ItemModule.Instance.GetNum(itemCid);
            var cfgItem = TableCenter.item.Get(itemCid);
            NoticeModule.ShowCostConfirm(APIUIPet.NoticeCid_SlotUnlockItem, itemCid, itemHave,
                this.OnCallClickSureUnlockSlot, cfgItem.Name, itemCost.ToString());
        }

        private void OnCallClickSureUnlockSlot()
        {
            var slotCostCidNum = TableCenter.global.PetUnlockAttributeSlotCost;
            int itemCid = slotCostCidNum[0];
            int itemCost = slotCostCidNum[1];
            int itemHave = ItemModule.Instance.GetNum(itemCid);
            if (itemHave < itemCost)
            {
                CfgItem cfgItem = TableCenter.item.Get(itemCid);
                NoticeModule.ShowNoticeNoCall(APIUIConst.NoticeCid_ItemNotEnough, cfgItem.Name);
                return;
            }
            this.SendUnlockSlot().Forget();
        }

        private async UniTaskVoid SendUnlockSlot()
        {
            var result = await PetModule.NetCore.CS_unlockSkillSlot(this.pet.id);
            if (result.IsSuccess)
            {
                this.pet.IncreaseUnlockSlot();
                this.RefreshCurrPetInfo();
            }
        }

        private void ShowPabilityGroups()
        {
            int cnt = APIUIPet.PabilityGroupNum;
            this.pabilityGroups.RefillCells(cnt);
        }

        private void OnPabilityGroupChanged(UIN_PetPabilityGroup item, int index)
        {
            item.Show(this.pet, index, this.OnCallClickPabilityGroupAttribute);
        }

        private void OnCallClickPabilityGroupAttribute(int groupIndex, int attributeIndex)
        {
            var list = this.pet.GetPabilityGroupList(groupIndex);
            int pabilityAttributeCid = list[attributeIndex];
            UIPetSlotType slotType = PetModule.Instance.GetPabilityAttributeSlotType(this.pet, pabilityAttributeCid);
            switch (slotType)
            {
                case UIPetSlotType.Used:
                    this.SendPutOffPabilityAttriubte(groupIndex + 1, pabilityAttributeCid).Forget();
                    break;
                case UIPetSlotType.Unlock:
                    this.SendPutOnPabilityAttriubte(groupIndex + 1, pabilityAttributeCid).Forget();
                    break;
                case UIPetSlotType.LockByLv:
                    this.ShowLockPabilityGroupTip(groupIndex);
                    break;
                default:
                    break;
            }
        }

        private async UniTaskVoid SendPutOnPabilityAttriubte(int groupId, int pabilityAttributeCid)
        {
            var result = await PetModule.NetCore.CS_putOnRandAttr(this.pet.id, groupId, pabilityAttributeCid);
            if (result.IsSuccess)
            {
                this.pet.AddUsingPabilityAttribute(pabilityAttributeCid);
                this.ShowSlots();
                this.ShowPabilityGroups();
            }
        }

        private async UniTaskVoid SendPutOffPabilityAttriubte(int groupId, int pabilityAttributeCid)
        {
            var result = await PetModule.NetCore.CS_putOffRandAttr(this.pet.id, groupId, pabilityAttributeCid);
            if (result.IsSuccess)
            {
                this.pet.RemoveUsingPabilityAttribute(pabilityAttributeCid);
                this.ShowSlots();
                this.ShowPabilityGroups();
            }
        }

        private void ShowLockPabilityGroupTip(int groupIndex)
        {
            var pabilityUnlockLv = this.pet.cfgData.RandomPabilityUnlockLv[groupIndex];
            NoticeModule.ShowNoticeNoCall(APIUIPet.NoticeCid_GroupUnlockLv, pabilityUnlockLv.ToString());
        }

        private void ShowBaseInfo()
        {
            this.ShowName();
            this.ShowType();
            this.ShowLockState();
            this.ShowFreedomBtn();
            this.ShowExp();
            this.ShowLv();
            this.ShowUpBtnAndCost();
        }

        private void ShowName()
        {
            string name = this.pet.GetName();
            this.ui.textName.text = name;
        }

        private void ShowType()
        {
            var cfg = this.pet.cfgData;
            this.ui.textType.text = cfg.TypeName;
        }

        private void ShowLockState()
        {
            int index = this.pet.isLock ? 0 : 1;
            //this.ui.btnLockState.background.indexSwitchSprite = index;
        }

        private void ShowFreedomBtn()
        {
            bool isActive = !this.pet.isLock && this.pet.currWearer == null;
            this.ui.btnFreedom.SetActive(isActive);
        }

        private void ShowExp()
        {
            var cfgCurrLv = this.pet.cfgLevel;
            var cfgMaxLv = this.pet.cfgMaxLevel;
            bool isMaxLv = cfgCurrLv == cfgMaxLv;
            int curr = isMaxLv ? 1 : this.pet.exp;
            int next = isMaxLv ? 1 : cfgCurrLv.NextEXP;
            this.ui.expBar.SetValue(curr, next);
        }

        private void ShowLv()
        {
            this.ui.textLv.text = this.pet.level.ToString();
            var cfgMaxLv = this.pet.cfgMaxLevel;
            this.ui.textLvMax.text = "/" + cfgMaxLv.Id;
        }

        private void ShowUpBtnAndCost()
        {
            var cfgCurrLv = this.pet.cfgLevel;
            var cfgMaxLv = this.pet.cfgMaxLevel;
            bool isMaxLv = cfgCurrLv == cfgMaxLv;
            if (isMaxLv)
            {
                this.ui.btnUpdate.SetActive(false);
                return;
            }

            int itemCid = TableCenter.global.PetExpItemCid;
            int costValue = cfgCurrLv.NextEXP - this.pet.exp;
            this.costMoney.Show(itemCid, costValue);
            this.ui.btnUpdate.SetActive(true);
        }

        private void OnClickBtnUpdate()
        {
            if (!this.costMoney.CheckIsEnough())
            {
                return;
            }
            this.SendUpLevel().Forget();
        }

        private async UniTaskVoid SendUpLevel()
        {
            int itemCid = TableCenter.global.PetExpItemCid;
            int costValue = this.pet.cfgLevel.NextEXP - this.pet.exp;
            var result = await PetModule.NetCore.CS_upLevel(this.pet.id, costValue);
            if (result.IsSuccess)
            {
                PetModule.Instance.UpdateOrNewPet(result.petPOD);
                this.RefreshCurrPetInfo();
            }
        }

        private void RefreshCurrPetInfo()
        {
            (this.parentNode as UIPetWarehouse).RefreshCurrPetInfo(this.pet.id);
        }

        private void ResfreshPetWarehouse()
        {
            (this.parentNode as UIPetWarehouse).RefreshWarehouse();
        }

        private void OnClickBtnFreedom()
        {
            var itemCidNums = ListPool<int>.Get();
            itemCidNums.AddRange(pet.cfgData.ReleaseReward);

            int expAll = this.GetPetCostAllExp();
            if (expAll > 0)
            {
                itemCidNums.Add(TableCenter.global.PetExpItemCid);
                itemCidNums.Add(expAll);
            }

            NoticeModule.ShowCostConfirm(APIUIPet.NoticeCid_PetFreedom, itemCidNums,
                this.OnCallSureFreedom, pet.GetName());

            ListPool<int>.Put(itemCidNums);
        }

        private int GetPetCostAllExp()
        {
            int exp = this.pet.exp;
            for (var i = 1; i < this.pet.level; i++)
            {
                var cfg = TableCenter.petLevel.Get(i);
                exp += cfg?.NextEXP ?? 0;
            }
            return exp;
        }

        private void OnCallSureFreedom()
        {
            this.SendFreedomPet().Forget();
        }

        private async UniTaskVoid SendFreedomPet()
        {
            var result = await PetModule.NetCore.CS_free(this.pet.id);
            if (result.IsSuccess)
            {
                this.ResfreshPetWarehouse();
            }
        }

        private void OnClickBtnChangeLockState()
        {
            this.SendChangeLockState().Forget();
        }

        private async UniTaskVoid SendChangeLockState()
        {
            bool isLockState = !this.pet.isLock;
            var result = await PetModule.NetCore.CS_lock(this.pet.id, isLockState);
            if (result.IsSuccess)
            {
                this.pet.UpdataLockState(isLockState);
                this.RefreshCurrPetInfo();
            }
        }

        private void OnClickChangeName()
        {
            this.OpenUI<UIPetEditName>(UD_PetEditName.Create(this.pet));
        }

        private void OnMsgPetRenameSuccess()
        {
            this.RefreshCurrPetInfo();
        }
        #endregion methonds
    }
}
